#include "dr16.hpp"
#include "UI.hpp"

/**
 * @brief 对象初始化
 *
 */
DR16::DR16(void) {
    reset();
}

/**
 * @brief 初始化遥控器以及遥控器事件
 *
 */
void DR16::init(void) {
    DMALIB_UART_Receive_IT(&DBUS_USART, data, DR16_RECEIVE_SIZE);

    event     = rt_event_create("dr16", RT_IPC_FLAG_PRIO);
    rc_thread = rt_thread_create("rc", rc_thread_entry, (void *)this, 1024, 4, 10);

    rt_thread_startup(rc_thread);
}
/**
 * @brief 初始化遥控器
 *
 */
void DR16::reset(void) {
    rc_.left_x_ = rc_.left_y_ = rc_.right_x_ = rc_.right_y_ = rc_.wheel_ = 1024;
    pc_.x_ = pc_.y_ = pc_.z_ = pc_.pressing_button_ = pc_.press_down_button_ = pc_.press_down_v_ = pc_.pressing_v_ =
        pc_.v_                                                                                   = 0;

    rc_.left_sw_  = SW_DOWN;
    rc_.right_sw_ = SW_MID;
}

/**
 * @brief 解码遥控器数据
 *
 */
void DR16::decode(void) {
    rc_.right_x_ = ((int16_t)data[0] | ((int16_t)data[1] << 8)) & 0x07FF;
    rc_.right_y_ = (((int16_t)data[1] >> 3) | ((int16_t)data[2] << 5)) & 0x07FF;
    rc_.left_x_  = (((int16_t)data[2] >> 6) | ((int16_t)data[3] << 2) | ((int16_t)data[4] << 10)) & 0x07FF;
    rc_.left_y_  = (((int16_t)data[4] >> 1) | ((int16_t)data[5] << 7)) & 0x07FF;
    rc_.wheel_   = ((int16_t)data[16] | ((int16_t)data[17] << 8)) & 0x07FF;

    rc_.left_sw_  = ((data[5] >> 4) & 0x000C) >> 2;
    rc_.right_sw_ = ((data[5] >> 4) & 0x0003);
    pc_.x_        = ((int16_t)data[6]) | ((int16_t)data[7] << 8);
    pc_.y_        = ((int16_t)data[8]) | ((int16_t)data[9] << 8);
    pc_.z_        = ((int16_t)data[10]) | ((int16_t)data[11] << 8);

    pc_.button_ = ((data[12] << 1) | data[13]);
    /* 鼠标事件处理 */
    for (int i = 0; i < 2; i++) {
        /* 鼠标被按下，且之前未被按下 */
        if (pc_.button_ & (1 << i) && !(pc_.pressing_button_ & (1 << i))) {
            pc_.press_down_button_ |= 1 << i;
        }
    }
    pc_.pressing_button_ = pc_.button_;

    pc_.v_ = ((int16_t)data[14] | ((int16_t)data[15] << 8));
    /* 键盘事件处理 */
    for (int i = 0; i < 16; i++) {
        /* 被按下 */
        if (pc_.v_ & (1 << i)) {
            /* 之前未被按下 */
            if (!(pc_.pressing_v_ & (1 << i))) {
                pc_.press_down_v_ |= 1 << i;
            }
        }
        /* 之前被按下 */
        else if (pc_.pressing_v_ & (1 << i)) {
            pc_.clicked_v_ |= 1 << i;
        }
    }
    pc_.pressing_v_ = pc_.v_;

    rt_event_send(event, DR16_EVENT_ONLINE);
}

/**
 * @brief 在线事件接收
 *
 * @return rt_err_t
 */
rt_err_t DR16::event_recv(void) {
    return rt_event_recv(event, DR16_EVENT_ONLINE, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 50, RT_NULL);
}

/**
 * @brief 遥控线程
 *
 * @param parameter
 */
void DR16::rc_thread_entry(void *parameter) {
    rt_err_t ret;
    DR16    *t_dr16 = (DR16 *)parameter;

    while (1) {
        ret = t_dr16->event_recv();

        /* 遥控器断开连接 */
        if (ret != RT_EOK) {
            t_dr16->reset();
					ui.ctrl=1;
        }
        // t_dr16->debug();
    }
}

/**
 * @brief 访问遥控器数据
 *
 * @return struct __RC
 */
__RC DR16::get_rc(void) {
    return rc_;
}
/**
 * @brief 访问PC数据
 *
 * @return struct __PC
 */
__PC DR16::get_pc(void) {
    return pc_;
}

/**
 * @brief 鼠标按键是否正在被按下（右：0，左：1）
 *
 * @param button 要查询的按键
 * @return true 被按下
 * @return false 未被按下
 */
bool DR16::is_button_pressing(uint8_t button) {
    return pc_.pressing_button_ & button;
}

/**
 * @brief 鼠标按键是否被按下（仅触发一次，右：0，左：1）
 *
 * @param button 要查询的按键
 * @return true 被按下
 * @return false 未被按下
 */
bool DR16::is_button_pressed_down(uint8_t button) {
    bool result = pc_.press_down_button_ & button;
    pc_.press_down_button_ &= ~button;
    return result;
}

/**
 * @brief 键盘按键是否按下（仅触发一次）
 *
 * @param key 要查询的按键，可用或运算判断多个按键
 * @return bool 是否按下
 */
bool DR16::is_key_pressed_down(uint16_t key) {
    bool result = pc_.press_down_v_ & key;
    pc_.press_down_v_ &= ~key;
    return result;
}

/**
 * @brief 按键是否点击（按下后弹起则有效）
 *
 * @param key 要查询的按键
 * @return uint16_t 是否点击
 */
bool DR16::is_key_clicked(uint16_t key) {
    bool result = pc_.clicked_v_ & key;
    pc_.clicked_v_ &= ~key;
    return result;
}

/**
 * @brief 按键是否正在被按下（会连续触发）
 *
 * @param key 要查询的按键
 * @return bool 是否按下
 */
bool DR16::is_key_pressing(uint16_t key) {
    return pc_.pressing_v_ & key;
}

/**
 * @brief 调试函数
 *
 */
void DR16::debug(void) {
//    for (int i = 0; i < 16; i++) {
//        rt_kprintf("%02X ", data[i]);
//    }
    rt_kprintf("%4d \n", rc_.wheel_);
}
